## Миксины


- Дорогой сеньор, добавь, пожалуйста, возможность логирования точек (товаров магазина).

И как бы вы поступили на месте этого сеньора? 
Плохой сеньор начнет прописывать логику логирования либо непосредственно в базовом классе Goods, либо уровнем выше (в иерархии наследования). 
А хороший воспользуется идеей миксинов. Для этого он создаст еще один класс, который можно назвать:

Структура

```python
class Point:
    def __init__(self, x, y):
        super().__init__()

    def __repr__(self):
        return f'Я точка'

class MixinLog:
    def __init__(self):
        print(f"Инициализация миксина")

    def hello(self):
        print(f"вызов миксин-метода")


class Point3D(Point, MixinLog):
    def __init__(self, x, y, z):
        self.__z = z
        super().__init__(x, y)

    def __repr__(self):
        return f'Я 3D-точка'


p = Point3D(1, 2 ,3)
pprint(Point3D.__mro__)
print(p)

```



```python
from datetime import datetime


class MixinLog:
    ID = 0
    def __init__(self):
        MixinLog.ID += 1
        self.id = MixinLog.ID
        print(f"Точку id #{self.id} создали в {datetime.now()}")

    def save_sell_log(self):
        f = open('log.txt', 'a', encoding='utf-8')
        print(f"Т{self.id} - {datetime.now()}", file=f)

```

Добавим этот класс в цепочку наследования:

> class Point3D(Point, MixinLog)

И видим ошибку. 
Очевидно, она связана с тем, что у второго класса MixinLog не был вызван инициализатор. 
Почему так произошло? Как мы уже знаем, при создании объектов инициализатор ищется сначала в дочернем классе, но так как его там нет, то в первом базовом 

Он там есть, выполняется и на этом инициализация нашего объекта Point3D завершается. Однако, нам нужно также взывать инициализатор и второго базового класса MixinLog. 

В данном случае, сделать это можно с помощью объекта-посредника super(), которая и делегирует вызов метода __init__ класса MixinLog:

```python
 super().__init__()
        print("init Goods")
```

Теперь, после запуска программы, мы видим, что оба инициализатора сработали и ошибок никаких нет.

Но откуда функция `super()` «знает», что нужно обратиться ко второму базовому классу `MixinLog`, а, скажем, не к базовому классу `object`, от которого неявно наследуются все классы верхнего уровня? 



MRO – Method Resolution Order говорит, в каком порядке обходить базовые классы: